package main

import (
	"encoding/json"
	"fmt"
	"github.com/tidwall/gjson"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"strings"
	"time"
)

//var (
//	APPID          = "wxecbd3c06c74eb0e1"	//订阅号id
//	APPSECRET      = "4bd75f6feb640d79b82b18a5e362d207"	//订阅号密匙
//	SentTemplateID = "CcBoXPSw8Egl4Is8APb8CMV3jr55HTZs8v_dhrEJgUk"	//模板ID，替换成自己的
//)

type token struct {
	AccessToken string `json:"access_token"`
	ExpiresIn   int    `json:"expires_in"`
}

//读取yaml文件，获取IP地址
type conf struct {
	Ip6 string `yaml:"ip6"`
	APPID string `yaml:"APPID"`
	APPSECRET string `yaml:"APPSECRET"`
	SentTemplateID string `yaml:"SentTemplateID"`
}

func main() {
	//定义一个ticker
	ticker := time.NewTicker(time.Millisecond * 60000)
	//停止ticker
	//ticker.Stop()
	//Ticker触发
	for  {
		<-ticker.C
		//do something
		//检查ip地址，如果IP地址改变则发送到微信
		checkIP()
	}
}

//发送动态ip
func sendmessage() {
	//从压yanl文件获取最新模板ID
	var c conf
	conf  :=c.getConf()
	SentTemplateID := conf.SentTemplateID

	//获取最新本地ip地址
	ip6,_ := getLocalIP()
	//fmt.Println(ip6)

	//关注着accesstoken
	access_token := getaccesstoken()
	if access_token == "" {
		return
	}
	//关注着，
	flist := getflist(access_token)
	if flist == nil {
		return
	}

	currenttime := time.Now().Format("2006-01-02 15:04:05")	//获取当前时间的字符串格式

	reqdata := "{\"IP\":{\"value\":\"ipv6地址:"+ip6+"\"}, \"TIME\":{\"value\":\"" +currenttime+ "\"}}"
	for _, v := range flist {
		templatepost(access_token, reqdata, SentTemplateID, v.Str)
	}
}

//获取关注着微信accesstoken
func getaccesstoken() string {
	//读取yaml信息
	var cf conf
	conf := cf.getConf()
	APPID := conf.APPID	//从yaml文件获取appid
	APPSECRET := conf.APPSECRET	//从yaml文件获取appsecret



	url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%v&secret=%v", APPID, APPSECRET)
	resp, err := http.Get(url)
	if err != nil {
		fmt.Println("获取微信token失败", err)
		return ""
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("微信token读取失败", err)
		return ""
	}

	token := token{}
	err = json.Unmarshal(body, &token)
	if err != nil {
		fmt.Println("微信token解析json失败", err)
		return ""
	}
	fmt.Println(token.AccessToken)
	return token.AccessToken
}

//获取关注者列表
func getflist(access_token string) []gjson.Result {
	url := "https://api.weixin.qq.com/cgi-bin/user/get?access_token=" + access_token + "&next_openid="
	resp, err := http.Get(url)
	if err != nil {
		fmt.Println("获取关注列表失败", err)
		return nil
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("读取内容失败", err)
		return nil
	}
	flist := gjson.Get(string(body), "data.openid").Array()
	return flist
}

//发送模板消息
func templatepost(access_token string, reqdata string, templateid string, openid string) {
	//获取ip地址
	ip6,_ := getLocalIP()

	url := "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + access_token
	gitea := "http://["+ip6+"]:3000"
	reqbody := "{\"touser\":\"" + openid + "\", \"template_id\":\"" + templateid + "\", \"url\":\""+gitea+"\", \"data\": " + reqdata +" }"
	fmt.Println("reqbody信息",reqbody)
	resp, err := http.Post(url,
		"application/x-www-form-urlencoded",
		strings.NewReader(string(reqbody)))
	if err != nil {
		fmt.Println(err)
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("返回信息：",string(body))
}



// 获取本机网卡IP
func getLocalIP() (ipv6 string, err error) {
	var (
		addrs   []net.Addr
		addr    net.Addr
		ipNet   *net.IPNet // IP地址
		isIpNet bool
	)
	// 获取所有网卡
	if addrs, err = net.InterfaceAddrs(); err != nil {
		return
	}
	// 取第一个非lo的网卡IP
	for _, addr = range addrs {
		// 这个网络地址是IP地址: ipv4, ipv6
		if ipNet, isIpNet = addr.(*net.IPNet); isIpNet && !ipNet.IP.IsLoopback() {
			// 跳过IPV4
			if ipNet.IP.To16() != nil {
				ipv6 = ipNet.IP.String() //2409:8a55:2e15:c980:319c:efe4:a6b3:9b8d
				//fmt.Println(ipv6)	//打印ip地址
				return
			}
		}
	}
	return
}

//读取yaml文件，获取参数
func (c *conf) getConf() *conf {
	yamlFile, err := ioutil.ReadFile("conf.yaml")
	if err != nil {
		fmt.Println(err.Error())
	}
	err = yaml.Unmarshal(yamlFile, c)
	if err != nil {
		fmt.Println(err.Error())
	}
	return c
}

//检查IP地址是否更新
func checkIP()  {
	//yaml读取数据
	//var cf conf
	//conf := cf.getConf()
	//fmt.Println(conf.Ip6) //打印读取的ip地址

	oldipv6 := read_ipv6()
	newIP6,_ := getLocalIP()
	if newIP6 == oldipv6{
		return
	}else {
		sendmessage()	//发送新的ip6到订阅号
		write_newIP6()	//更新ipv6.txt的ip6地址
	}
}


//txt读取ip6地址
func read_ipv6() (ipv6 string){
	// 打开文件，只读
	file, err := os.Open("ipv6.txt")
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	// 从文件中读取len(b)字节的文件。
	// 返回0字节意味着读取到文件尾了
	// 读取到文件会返回io.EOF的error
	byteSlice := make([]byte, 39)
	bytesRead, err := file.Read(byteSlice)
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Number of bytes read: %d\n", bytesRead)
	log.Printf("Data read: %s\n", byteSlice)

	ipv6 = string(byteSlice)
	fmt.Println(ipv6)
	return ipv6
}
//txt更新的ip6地址
func write_newIP6() {
	//获取ip6
	ip6, _ := getLocalIP()

	//创建并写入文件内容
	err := ioutil.WriteFile("ipv6.txt", []byte(ip6), 0666)
	if err != nil {
		log.Fatal(err)

	}
}